# -*- shell-script -*-

# 00minimal - Hardware database routines and variables for
#             systems with device-tree, with ibm,vpd properties.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 2002, 2003, 2004, 2005

# Maintained by Martin Schwenke <martins@au.ibm.com>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    
# $Id: 00minimal,v 1.1 2006/04/11 18:38:28 emunson Exp $

true || return 0

######################################################################

usage ()
{
    cat <<EOF 1>&2
usage: $0 [ -A | -d name ] [ -r | -c ] [ -D db | -z tgz ]
options: -h      print this usage message
         -c      Do not use menus.  This is the default (no menus implemented).
         -r      Use a tabular format.  Overrides -c.
         -A      Display microcode level for as many devices as possible.
                 This implies -r.
	 -d name Only display microcode level for specified device.
	 -D db   Directory db contains database, instead of default.
	 -z tgz  File tgz contains database archive (overrides -d).
EOF
    exit 1
}

process_options ()
{
    # Defaults.
    tabular=false
    all=false
    name=""

    options=":hcrAd:${db_path_option}:z:"
    while getopts ${options} opt "$@" ; do
	case $opt in
	    (h) usage                   ;;
	    (c) :                       ;; # Default!  For AIX compatibility.
	    (r) tabular=true            ;;
	    (A) all=true ; tabular=true ;;
	    (d) name="$OPTARG"          ;;
	    (${db_path_option}|z) :     ;; # Done by process_db_path_options().
	    \?) echo "unknown option \`${OPTARG}'" 1>&2
                echo 1>&2
		usage
		;;
	esac
    done

    shift $((${OPTIND} - 1))
    [ -n "$1" ] && usage
    "$all" && [ -n "$name" ] && usage
    return 0
}

######################################################################

should_render ()
{
    lsmcode_should_render "$@"
}

lsmcode_should_render ()
{
    local dir="$1"
    local ds="$2"
    local ax="$3"
    local yl="$4"

    $all && return 0

    [ -z "$name" ] && lsmcode_is_sys "$ds" && return 0

    if [ -n "$name" ] ; then
	should_render_basic "$@"
    else
	return 1
    fi
}

render_all ()
{
    local sys_output other_output

    render_all_basic
    
    if [ -n "$sys_output" ] ; then
	$tabular && sys_output="sys0!${sys_output}"
	echo "${sys_output}"
    fi

    [ -n "$other_output" ] && echo "$other_output"

    # Return value.
    [ -n "$sys_output" -o -n "$other_output" ]
}

render_linux_vpd ()
{
    local x="$1"

    local node="${x%/linux,vpd}"

    local vpd_subdirs
    vpd_subdirs_list_hook "$node"
    local vpd_dir
    for vpd_dir in $vpd_subdirs ; do
	local vpd_value
	vpd_field_get "$vpd_dir" "AX"
	local ax="$vpd_value"
	vpd_field_get "$vpd_dir" "DS"
	local ds="$vpd_value"

	if should_render "$node" "$ds" "$ax" "" ; then
	    lsmcode_render_vpd "$vpd_dir" "$ax" "$ds"
	fi
    done
}

######################################################################

lsmcode_is_sys ()
{
    local ds="$1"

    [ "$ds" = "System Firmware" ] || lsmcode_is_service_processor "$ds"
}

lsmcode_is_service_processor ()
{
    local ds="$1"

    [   "$ds" = "Service Processor" -o \
	"$ds" = "Platform Firmware" -o \
	"$ds" = "SP_CARD_" -o \
	"$ds" = "Service Processor Firmware" ]
}

lsmcode_render_vpd ()
{
    local vpd_dir="$1"
    local ax="$2"
    local ds="$3"

    if lsmcode_is_sys "$ds" ; then
	lsmcode_render_sys_vpd "$vpd_dir" "$ax" "$ds"
    else
	lsmcode_render_other_vpd "$vpd_dir" "$ax" "$ds"
    fi
}

lsmcode_get_current_firmware ()
{
    # Sets: lsmcode_current_firmware
    lsmcode_current_firmware="b"
}

lsmcode_render_sys_vpd ()
{
    local vpd_dir="$1"
    local ax="$2"
    local ds="$3"

    local vpd_value version

    local nl="
" # Not a bug!

    if [ "$ds" = "System Firmware" ] ; then
	vpd_field_get "$vpd_dir" "MI"
	version="$vpd_value"
	if [ -n "$version" ] ; then
	    local v_p="${version#* }" ; v_p="${v_p% *}"
	    local lsmcode_current_firmware
	    lsmcode_get_current_firmware
	    version="${version%% *} (t) ${v_p} (p) ${version##* }"
	    version="${version} (${lsmcode_current_firmware})"

	    # Get service processor version too.
	    local s v spv
	    s=0
	    vpd_field_get "$vpd_dir" "CL" $s
	    while [ -z "$spv" -a -n "$vpd_value" ] ; do
		case "$vpd_value" in
		    (PFW\ *) spv="${vpd_value#* }" ;;
		    *)  s=$(($s + 1))
			vpd_field_get "$vpd_dir" "CL" $s
			;;
		esac
	    done
	    if [ -n "$spv" ] ; then
		if $tabular ; then
		    sys_output="service:${spv}"
		else
		    sys_output="Version of PFW is ${spv}"
		fi
	    fi
	else
	    vpd_field_get "$vpd_dir" "RM"
	    version="$vpd_value"
	fi

	if [ -n "$version" ] ; then
	    if $tabular ; then
		[ -n "$sys_output" ] && sys_output="|${sys_output}"
		sys_output="system:${version}${sys_output}"
	    else
		[ -n "$sys_output" ] && sys_output="${nl}${sys_output}"
		sys_output="Version of ${ds} is ${version}${sys_output}"
	    fi
	fi
    elif lsmcode_is_service_processor "$ds" ; then
	vpd_field_get "$vpd_dir" "RM"
	version="$vpd_value"
	if [ -z "$version" ] ; then
	    vpd_field_get "$vpd_dir" "RL"
	    version="$vpd_value"
	fi
	if [ -n "$version" ] ; then
	    if $tabular ; then
		[ -n "$sys_output" ] && sys_output="${sys_output}|"
		sys_output="${sys_output}service:${version}"
	    else
		[ -n "$sys_output" ] && sys_output="${sys_output}${nl}"
		sys_output="${sys_output}Version of ${ds} is ${version}"
	    fi
	fi
    else
	: "lsmcode_render_sys_vpd: unhandled DS=\"${ds}\""
    fi
}

lsmcode_render_other_vpd ()
{
    local vpd_dir="$1"
    local ax="$2"
    local ds="$3"

    local vpd_value version

    local nl="
" # Not a bug!

    vpd_field_get "$vpd_dir" "RM"
    version="$vpd_value"
    if [ -z "$version" ] ; then
	vpd_field_get "$vpd_dir" "RL"
	version="$vpd_value"
    fi
    [ -n "$version" ] || return
    
    vpd_field_get "$vpd_dir" "TM"
    local tm="$vpd_value"
    if [ -n "$tm" ] ; then
	vpd_field_get "$vpd_dir" "UL"
	local ul="$vpd_value"
	if [ -n "$ul" ] ; then
	    local ul_hex=$(tdump -c -s "$ul")
	    version="${tm:0:7}.${ul_hex}.${version}"
    	elif [ -n "$ds" -a -z "${ds/*SCSI*/}" ] ; then
	    vpd_field_get "$vpd_dir" "UM"
	    local um="${vpd_value// /}"
	    vpd_field_get "$vpd_dir" "UT"
	    local ut="${vpd_value// /}" 
	    vpd_field_get "$vpd_dir" "UF"
	    local uf="$vpd_value"
	    vpd_field_get "$vpd_dir" "MF"
	    local mf="$vpd_value"
	    if [ -n "$um" -a -n "$ut" -a -n "$uf" -a -n "$mf" ] ; then
		version="${mf}-${tm:0:10}.${um:0:3}-${ut:0:8}.${version}.${uf}"
	    else
		version="${tm}.${version}"
	    fi
	else
	    version="${tm}.${version}"
	fi
    fi

    local label="$ds"
    $tabular && [ -n "$ax" ] && label="$ax"
	
    [ -n "$other_output" ] && other_output="${other_output}${nl}"
    if $tabular ; then
	other_output="${other_output}${label}!${version}"
    else
	other_output="${other_output}Version of ${ds} is ${version}"
    fi
}

